package EventManager;

import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

public class EventManager
{
	private static EventManager ref;
	private LinkedList<EventType> m_activeEvents;
	private LinkedList<EventType> m_eventQueue;
	private LinkedList<Listener> m_listenerList;

	private EventManager()
	{
		m_listenerList = new LinkedList<Listener>();
		m_eventQueue = new LinkedList<EventType>();
		m_activeEvents = new LinkedList<EventType>();
	}
	/**
	 * Creates an EventManager Singleton
	 * @return EventManager Object
	 */
	public static EventManager getInstance()
	{
		if (ref == null)
			// it's ok, we can call this constructor
			ref = new EventManager();
		return ref;
	}
	/**
	 * Check for duplicates before adding the listener
	 */
	public boolean addListener(Listener listener)
	{
		if (!searchListenerList(listener))
		{
			m_listenerList.addFirst(listener);
			return true;
		}
		return false;
	}
	/**
	 * Deletes listener from the ListenerList
	 */
	public boolean deleteListener(Listener listener)
	{
		if (m_listenerList.contains(listener))
		{
			m_listenerList.remove(listener);
			return true;
		}
		return false;
	}
	/**
	 * adds an event to the EventQueue
	 */
	public boolean queueEvent(EventType event)
	{
		if (m_eventQueue.size() == 0)
		{
			m_eventQueue.addLast(event);
			return true;
		} else if (event.getName().equals(m_eventQueue.getLast().getName()))
		{
			m_eventQueue.removeLast();
			m_eventQueue.addLast(event);
			return true;
		} else
		{
			m_eventQueue.addLast(event);
			return true;
		}
	}
	/**
	 * Adds a event by string name to the EventQueue
	 */
	public boolean queueEvent(String eventName)
	{
		// Create the event to add based on the passed in char
		EventType event = new EventType(eventName);
		if (m_eventQueue.size() == 0)
		{
			m_eventQueue.addLast(event);
			return true;
		}
		if (eventName.equals(m_eventQueue.getLast().getName()))
		{
			m_eventQueue.removeLast();
			m_eventQueue.addLast(event);
		} else
		{
			m_eventQueue.addLast(event);
			return true;
		}
		return false;
	}
	/**
	 * Deletes the event from the EventQueue
	 */
	public void deleteEvent(EventType event)
	{
		m_eventQueue.remove(event);
	}
	/**
	 * Deletes all events with the same name as eventName
	 */
	public boolean deleteEvent(String eventName)
	{
		for (EventType e : m_eventQueue)
		{
			if (e.getName().equals(eventName))
			{
				m_eventQueue.remove(e);
				return true;
			}
		}
		return false;
	}
	/**
	 * search for duplicate listener
	 * @return true if found listener, false otherwise
	 */
	public boolean searchListenerList(Listener listener)
	{
		return m_listenerList.contains(listener);
	}
	/**
	 * Adds all events inside of m_eventQueue to m_activeEvents Iterates through
	 * m_activeEvents running
	 * @throws IOException 
	 */
	public void processEvents() throws IOException
	{
		// Only run for 5ms, getting called every gameloop
		long endTime = System.currentTimeMillis() + 5;
		// Push all of EventQueue to ActiveQueue
		while (m_eventQueue.size() > 0)
		{
			m_activeEvents.addLast(m_eventQueue.getLast());
			m_eventQueue.removeLast();
		}
		
		while ((m_activeEvents.size() > 0))
		{
			if (System.currentTimeMillis() > endTime)
			{
				return;
			}
			// Iterate through ActiveQueue until finished or endTime reached
			Iterator<Listener> it = m_listenerList.iterator();			
			while (it.hasNext() && m_activeEvents.size() > 0)
			{		
				Listener temp = it.next();
				if (temp.HandleEvent(m_activeEvents.getLast()))
				{
					m_activeEvents.removeLast();
				}
				else if (!it.hasNext())
				{
					//if there are no listeners left, then we couldn't handle the event.
					//Queue it up once more and see if it gets picked up
					m_eventQueue.add(m_activeEvents.getLast());
					m_activeEvents.removeLast();
				}
			}
		}
		
	}
}